package br.uvv.sao.dao;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import br.uvv.sao.domain.Alternativa;
import br.uvv.sao.domain.Aluno;
import br.uvv.sao.domain.AlunoOferta;
import br.uvv.sao.domain.OfertaDisciplina;
import br.uvv.sao.domain.Prova;
import br.uvv.sao.domain.ProvaRealizada;
import br.uvv.sao.domain.Questao;
import br.uvv.sao.domain.QuestaoMarcadaProvaRealizada;
import br.uvv.sao.util.DAOException;

@SuppressWarnings("unchecked")
public class RealizarProvaDAO extends DAO {
	private static final long serialVersionUID = 8727494153232227679L;

	public List<Prova> getListProvas(Aluno alunoInstance, Date buscaAno,
			String buscaSemestre, Long buscaDisciplina, Long buscaProfessor) throws DAOException {
		List<Prova> modelList = new ArrayList<Prova>();
		try {
			begin();
			Criteria criteria = sessao.createCriteria(Aluno.class);
			criteria.add(Restrictions.eq("id", alunoInstance.getId()));
			List<Long> alunosID = new ArrayList<Long>();
			List<Aluno> alunosTemp = criteria.list();
			commit();
			for (Aluno aluno : alunosTemp) {
				alunosID.add(aluno.getId());
			}
			begin();
			List<Long> ofertasID = new ArrayList<Long>();
			List<OfertaDisciplina> ofertasTemp = new ArrayList<OfertaDisciplina>();
			criteria = sessao.createCriteria(OfertaDisciplina.class);
			if(buscaSemestre != null && buscaSemestre != ""){
				criteria.add(Restrictions.eq("semestre", buscaSemestre));
			}
			if(buscaAno != null){
				criteria.add(Restrictions.eq("ano", buscaAno));
			}
			criteria.createCriteria("alunosMatriculados")
					.createCriteria("aluno")
					.add(Restrictions.in("id", alunosID));
			if(buscaDisciplina != null && buscaDisciplina > 0){
				criteria.createCriteria("disciplina").add(Restrictions.eq("id", buscaDisciplina));
			}
			if(buscaProfessor != null && buscaProfessor > 0){
				criteria.createCriteria("professor").add(Restrictions.eq("id", buscaProfessor));
			}
			ofertasTemp = criteria.list();
			for (OfertaDisciplina ofertaDisciplina : ofertasTemp) {
				ofertasID.add(ofertaDisciplina.getId());
			}
			commit();
			if(ofertasID.size() > 0){
				begin();
				criteria = sessao.createCriteria(Prova.class);
				criteria.createCriteria("aplicadaEm").add(Restrictions.in("id", ofertasID));
				criteria.addOrder(Order.desc("dataHoraInicio"));
				criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
				modelList = criteria.list();
				commit();
			}else{
				modelList = new ArrayList<Prova>();
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new DAOException(e);
		}
		return modelList;
	}

	public List<Questao> getListQuestoes(Prova provaInstance) throws DAOException {
		List<Questao> modelList = new ArrayList<Questao>();
		try {
			begin();
			Criteria criteria = sessao.createCriteria(Questao.class);
			criteria.createCriteria("provas").add(Restrictions.eq("id", provaInstance.getId()));
			criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
			modelList = criteria.list();
			commit();
		} catch (Exception e) {
			e.printStackTrace();
			throw new DAOException(e);
		}
		return modelList;
	}

	public Alternativa getAlternativa(Long alternativaMarcada) throws DAOException {
		String[] fetchMode = {"questao"};
		return (Alternativa) get(Alternativa.class, alternativaMarcada, fetchMode);
	}

	public AlunoOferta getAlunoOferta(OfertaDisciplina aplicadaEm, Aluno aluno) throws DAOException {
		Criterion[] filtros = {Restrictions.eq("ofertaDisciplina", aplicadaEm), Restrictions.eq("aluno", aluno)};
		String[] fetchMode = {"ofertaDisciplina"};
		return (AlunoOferta) get(AlunoOferta.class, fetchMode, filtros);
	}

	public ProvaRealizada getProvaRealizada(Prova provaInstance, AlunoOferta oferta, Questao questao) throws DAOException {
		Criterion[] filtros = {Restrictions.eq("provaReferencia", provaInstance), Restrictions.eq("alunoOferta", oferta), Restrictions.eq("questaoReferencia", questao)};
		String[] fetchMode = {"alunoOferta", "provaReferencia", "questaoReferencia"};
		return (ProvaRealizada) get(ProvaRealizada.class, fetchMode, filtros);
	}

	public QuestaoMarcadaProvaRealizada getQuestaoMarcada(
			ProvaRealizada provaRealizada, Questao questao) throws DAOException {
		Criterion[] filtros = {Restrictions.eq("provaReferencia", provaRealizada), Restrictions.eq("questaoReferencia", questao)};
		String[] fetchMode = {"provaReferencia", "questaoReferencia"};
		return (QuestaoMarcadaProvaRealizada) get(QuestaoMarcadaProvaRealizada.class, fetchMode, filtros);
	}

	public void salvar(ProvaRealizada provaRealizada) throws DAOException {
		begin();
		sessao.saveOrUpdate(provaRealizada);
		commit();
	}

	public void salvar(QuestaoMarcadaProvaRealizada questaMarcada) throws DAOException {
		begin();
		sessao.saveOrUpdate(questaMarcada);
		commit();
	}

	public List<ProvaRealizada> listarProvasRealizadas(Prova provaInstance,
			AlunoOferta oferta) throws DAOException {
		Criterion[] filtros = {Restrictions.eq("provaReferencia", provaInstance), Restrictions.eq("alunoOferta", oferta)};
		String[] fetchMode = {"alunoOferta", "provaReferencia"};
		return list(ProvaRealizada.class, fetchMode, filtros);
	}

	public void atualizar(Questao questao) throws DAOException {
		begin();
		sessao.update(questao);
		commit();
	}
}
